/*
 * @[H]:  Copyright (c) 2021 Phytium Information Technology, Inc. 
 * 
 *  SPDX-License-Identifier: Apache-2.0. 
 * 
 * @Date: 2021-08-05 17:32:11
 * @LastEditTime: 2021-08-16 15:58:17
 * @Description:  Description of file
 * @Modify History: 
 * * * Ver   Who        Date         Changes
 * * ----- ------     --------    --------------------------------------
 */

#include "f_pcie.h"
#include "f_pcie_hw.h"
#include "ft_assert.h"
#include "ft_debug.h"
#define FPCIE_INTR_DEBUG_TAG "FPCIE_INTR"
#define FPCIE_INTR_ERROR(format, ...) FT_DEBUG_PRINT_E(FPCIE_INTR_DEBUG_TAG, format, ##__VA_ARGS__)
#define FPCIE_INTR_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(FPCIE_INTR_DEBUG_TAG, format, ##__VA_ARGS__)
#define FPCIE_INTR_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(FPCIE_INTR_DEBUG_TAG, format, ##__VA_ARGS__)

LONG FPcieSetHandler(FPcie *instance_p, u32 handler_type,
                     void *func_pointer, void *call_back_ref)
{
    LONG status;
    FT_ASSERTNONVOID(instance_p != NULL);
    FT_ASSERTNONVOID(func_pointer != NULL);
    FT_ASSERTNONVOID(instance_p->is_ready == (u32)FT_COMPONENT_IS_READY);

    switch (handler_type)
    {
    case FPCIE_HANDLER_DMASEND:
        status = (LONG)(FT_SUCCESS);
        instance_p->fpcie_dma_tx_cb = ((FPcieIrqCallBack)(void *)func_pointer);
        instance_p->dma_tx_args = call_back_ref;
        break;
    case FPCIE_HANDLER_DMARECV:
        status = (LONG)(FT_SUCCESS);
        instance_p->fpcie_dma_rx_cb = ((FPcieIrqCallBack)(void *)func_pointer);
        instance_p->dma_rx_args = call_back_ref;
        break;
    case FPCIE_HANDLER_DMASEND_ERROR:
        status = (LONG)(FT_SUCCESS);
        instance_p->fpcie_dma_tx_error_cb = ((FPcieIrqCallBack)(void *)func_pointer);
        instance_p->dma_tx_error_args = call_back_ref;
        break;
    case FPCIE_HANDLER_DMARECV_ERROR:
        status = (LONG)(FT_SUCCESS);
        instance_p->fpcie_dma_rx_error_cb = ((FPcieIrqCallBack)(void *)func_pointer);
        instance_p->dma_rx_error_args = call_back_ref;
        break;
    default:
        status = (LONG)(FPCIE_ERR_INVALID_PARAM);
        break;
    }
    return status;
}

void FPcieMiscIrq(s32 vector, void *args)
{
    FPcie *instance_p = (FPcie *)args;
    uintptr_t control_address;
    u32 reg_value;
    (void)vector;
    FT_ASSERTVOID(instance_p != NULL);

    if (FPCIE_READREG(instance_p->config.peu0_config_address, FPCIE_REG_MISC_INT_STATE_OFFSET) & FPCIE_MISC_STATE_C0_DMA_INT_MASK)
    {
        FPCIE_INTR_DEBUG_I("PEU0 C0 DMA IRQ!");
        control_address = instance_p->config.control_c0_address;
    }
    else if (FPCIE_READREG(instance_p->config.peu0_config_address, FPCIE_REG_MISC_INT_STATE_OFFSET) & FPCIE_MISC_STATE_C1_DMA_INT_MASK)
    {
        FPCIE_INTR_DEBUG_I("PEU0 C1 DMA IRQ!");
        control_address = instance_p->config.control_c1_address;
    }
    else if (FPCIE_READREG(instance_p->config.peu0_config_address, FPCIE_REG_MISC_INT_STATE_OFFSET) & FPCIE_MISC_STATE_C2_DMA_INT_MASK)
    {
        FPCIE_INTR_DEBUG_I("PEU0 C2 DMA IRQ!");
        control_address = instance_p->config.control_c2_address;
    }
    else if (FPCIE_READREG(instance_p->config.peu1_config_address, FPCIE_REG_MISC_INT_STATE_OFFSET) & FPCIE_MISC_STATE_C0_DMA_INT_MASK)
    {
        FPCIE_INTR_DEBUG_I("PEU0 C0 DMA IRQ!");
        control_address = instance_p->config.control_c3_address;
    }
    else if (FPCIE_READREG(instance_p->config.peu1_config_address, FPCIE_REG_MISC_INT_STATE_OFFSET) & FPCIE_MISC_STATE_C1_DMA_INT_MASK)
    {
        FPCIE_INTR_DEBUG_I("PEU0 C1 DMA IRQ!");
        control_address = instance_p->config.control_c4_address;
    }
    else if (FPCIE_READREG(instance_p->config.peu1_config_address, FPCIE_REG_MISC_INT_STATE_OFFSET) & FPCIE_MISC_STATE_C2_DMA_INT_MASK)
    {
        FPCIE_INTR_DEBUG_I("PEU0 C2 DMA IRQ!");
        control_address = instance_p->config.control_c5_address;
    }

    FPCIE_INTR_DEBUG_I("pcie misc irq!");
    FPCIE_INTR_DEBUG_I("pcie dma irq status : 0x%08lx", FPCIE_READREG(control_address, FPCIE_REG_DMA_INT_STATUS_OFFSET));

    reg_value = FPCIE_READREG(control_address, FPCIE_REG_DMA_INT_STATUS_OFFSET);

    if (reg_value & FPCIE_CTRL_DMA_INT_STATUS_CH0_DONE_MASK)
    {
        if (instance_p->fpcie_dma_rx_cb)
        {
            instance_p->fpcie_dma_rx_cb(instance_p->dma_rx_args);
        }
    }

    if (reg_value & FPCIE_CTRL_DMA_INT_STATUS_CH1_DONE_MASK)
    {
        if (instance_p->fpcie_dma_tx_cb)
        {
            instance_p->fpcie_dma_tx_cb(instance_p->dma_tx_args);
        }
    }

    if (reg_value & FPCIE_CTRL_DMA_INT_STATUS_CH0_ERR_MASK)
    {
        if (instance_p->fpcie_dma_rx_error_cb)
        {
            instance_p->fpcie_dma_rx_error_cb(instance_p->dma_rx_error_args);
        }
    }

    if (reg_value & FPCIE_CTRL_DMA_INT_STATUS_CH1_ERR_MASK)
    {
        if (instance_p->fpcie_dma_tx_error_cb)
        {
            instance_p->fpcie_dma_tx_error_cb(instance_p->dma_tx_error_args);
        }
    }

    FPCIE_WRITEREG(control_address, FPCIE_REG_DMA_INT_STATUS_OFFSET, FPCIE_CTRL_DMA_INT_STATUS_ALL_MASK);
}